package in.controller.adapter; import android.content.Context; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import in.controller.adapter.base.RobinAdapter; import in.data.stream.base.Stream; import in.model.Post; import in.view.delegate.PostHiddenDelegate; import in.view.delegate.ThreadPostCollapsedDelegate; import in.view.delegate.ThreadPostDelegate; import in.view.delegate.ThreadPostSelectedDelegate; import lombok.Getter; import lombok.Setter; public class ThreadAdapter extends RobinAdapter<Post> { public enum Mode { STANDARD, NESTED; // TODO: Add support for replies to deleted posts } public static final int TYPE_POST = 0; public static final int TYPE_POST_SELECTED = 1; public static final int TYPE_POST_COLLAPSED_HEADER = 2; public static final int TYPE_POST_COLLAPSED_HIDDEN = 3; @Getter @Setter private Mode mode = Mode.STANDARD; @Getter @Setter private Post selectedPost; @Getter @Setter private HashMap<String, Integer> indentSpec; @Getter private HashMap<String, ArrayList<String>> collapsedReference = new HashMap<String, ArrayList<String>>(); public ThreadAdapter(Context context) { super(context); getItemTypes().put(TYPE_POST, new ThreadPostDelegate(this)); getItemTypes().put(TYPE_POST_SELECTED, new ThreadPostSelectedDelegate(this)); getItemTypes().put(TYPE_POST_COLLAPSED_HEADER, new ThreadPostCollapsedDelegate(this)); getItemTypes().put(TYPE_POST_COLLAPSED_HIDDEN, new PostHiddenDelegate(this)); } @Override public void setStream(Stream<Post> stream) { if (mode == Mode.STANDARD) { // ensure that the stream is in date order with newest first Collections.sort(stream.getItems(), new Comparator<Post>() { @Override public int compare(Post lhs, Post rhs) { return lhs.getDate() == rhs.getDate() ? 0 : (lhs.getDate() < rhs.getDate() ? 1 : -1); } }); super.setStream(stream); } else { // calculate the post replies into a map based on their originalId ArrayList<Post> postsList = new ArrayList<Post>(stream.getItems().size()); indentSpec = new HashMap<String, Integer>(stream.getItems().size()); for (int streamIndex = stream.getItems().size() - 1; streamIndex > -1; streamIndex--) { Post post = stream.getItems().get(streamIndex); int insertIndex = postsList.indexOf(post); if (post.getReplyTo() == null) { indentSpec.put(post.getOriginalId(), 1); } if (insertIndex < 0) { postsList.add(post); insertIndex = postsList.size(); } if (post.getReplyCount() > 0) { // Loop through each post in our list and find that post's replies ArrayList<Post> replies = new ArrayList<Post>(); for (int i = stream.getItems().size() - 1; i > -1; i--) { Post toMatch = stream.getItems().get(i); if (toMatch == null || toMatch.getReplyTo() == null || toMatch.equals(post)) continue; if (toMatch.getReplyTo().equals(post.getOriginalId()) && !postsList.contains(toMatch)) { replies.add(toMatch); int intIndent = indentSpec.get(toMatch.getReplyTo()) == null ? -1 : indentSpec.get(toMatch.getReplyTo()); indentSpec.put(toMatch.getOriginalId(), intIndent + 1); } } postsList.addAll(Math.min(insertIndex + 1, postsList.size()), replies); } } stream.getItems().clear(); for (int index = postsList.size() - 1; index > -1; index--) { stream.getItems().add(postsList.get(index)); } super.setStream(stream); } } @Override public Post getItem(int position) { return getStream().getItems().get(getCount() - 1 - position); } @Override public int getItemViewType(int position) { Post item = getItem(position); if (mode == Mode.STANDARD) { if (getCount() == 1 || item.equals(selectedPost)) { return TYPE_POST_SELECTED; } } else { Iterator<String> iterator = collapsedReference.keySet().iterator(); while (iterator.hasNext()) { String key = iterator.next(); if (collapsedReference.get(key).contains(item.getOriginalId())) { return TYPE_POST_COLLAPSED_HIDDEN; } } if (collapsedReference.containsKey(item.getOriginalId())) { return TYPE_POST_COLLAPSED_HEADER; } } return TYPE_POST; } }